"""
需求范围定义模型

定义需求范围的数据结构和相关操作
"""

from datetime import datetime
from typing import List, Dict, Any, Optional
from dataclasses import dataclass, field
import json
import uuid


@dataclass
class RequirementScope:
    """需求范围定义实体"""

    scope_id: str
    scope_name: str
    core_functions: List[str]
    scope_boundary: Dict[str, List[str]]
    justification: str
    excluded_functions: List[str] = field(default_factory=list)
    created_at: datetime = field(default_factory=datetime.now)
    updated_at: datetime = field(default_factory=datetime.now)

    def __post_init__(self):
        """初始化后处理"""
        if not self.scope_id:
            self.scope_id = f"scope_{int(datetime.now().timestamp())}_{str(uuid.uuid4())[:8]}"

        # 验证必要字段
        if not self.core_functions:
            raise ValueError("核心功能列表不能为空")

        if not self.justification:
            raise ValueError("范围定义理由不能为空")

        if not self.scope_boundary or 'includes' not in self.scope_boundary:
            raise ValueError("范围边界定义不完整")

    @classmethod
    def create_new(cls, scope_name: str, core_functions: List[str],
                   justification: str, excluded_functions: List[str] = None) -> 'RequirementScope':
        """创建新的需求范围定义"""
        scope_boundary = cls._generate_scope_boundary(core_functions, excluded_functions or [])

        return cls(
            scope_id="",  # 将在__post_init__中生成
            scope_name=scope_name,
            core_functions=core_functions,
            excluded_functions=excluded_functions or [],
            scope_boundary=scope_boundary,
            justification=justification
        )

    @staticmethod
    def _generate_scope_boundary(core_functions: List[str],
                               excluded_functions: List[str]) -> Dict[str, List[str]]:
        """生成范围边界定义"""
        # 基于功能类别推断范围边界
        includes = set()
        excludes = set()

        # 核心功能相关的类别
        core_categories = ["文档分析", "需求处理", "清晰度评估", "范围确认"]
        non_core_categories = ["资产管理", "IP管理", "账号密码", "用户认证"]

        includes.update(core_categories)
        excludes.update(non_core_categories)

        # 根据具体功能调整边界
        for func in core_functions:
            if any(keyword in func for keyword in ["文档", "分析", "评估"]):
                includes.add("文档处理")
            elif any(keyword in func for keyword in ["需求", "澄清"]):
                includes.add("需求管理")

        for func in excluded_functions:
            if any(keyword in func for keyword in ["资产", "IP"]):
                excludes.add("资产管理")
            elif any(keyword in func for keyword in ["账号", "密码", "认证"]):
                excludes.add("用户管理")

        return {
            "includes": sorted(list(includes)),
            "excludes": sorted(list(excludes))
        }

    def update_scope(self, core_functions: List[str] = None,
                    excluded_functions: List[str] = None,
                    justification: str = None) -> None:
        """更新范围定义"""
        if core_functions is not None:
            self.core_functions = core_functions

        if excluded_functions is not None:
            self.excluded_functions = excluded_functions

        if justification is not None:
            self.justification = justification

        # 重新生成范围边界
        self.scope_boundary = self._generate_scope_boundary(
            self.core_functions,
            self.excluded_functions
        )

        self.updated_at = datetime.now()

    def add_core_function(self, function: str) -> None:
        """添加核心功能"""
        if function not in self.core_functions:
            self.core_functions.append(function)
            self.update_scope()

    def remove_core_function(self, function: str) -> None:
        """移除核心功能"""
        if function in self.core_functions:
            self.core_functions.remove(function)
            self.update_scope()

    def add_excluded_function(self, function: str) -> None:
        """添加排除功能"""
        if function not in self.excluded_functions:
            self.excluded_functions.append(function)
            self.update_scope()

    def remove_excluded_function(self, function: str) -> None:
        """移除排除功能"""
        if function in self.excluded_functions:
            self.excluded_functions.remove(function)
            self.update_scope()

    def is_function_in_scope(self, function: str) -> bool:
        """检查功能是否在范围内"""
        return function in self.core_functions

    def is_function_excluded(self, function: str) -> bool:
        """检查功能是否被排除"""
        return function in self.excluded_functions

    def get_scope_summary(self) -> Dict[str, Any]:
        """获取范围摘要"""
        return {
            "scope_id": self.scope_id,
            "scope_name": self.scope_name,
            "core_functions_count": len(self.core_functions),
            "excluded_functions_count": len(self.excluded_functions),
            "includes_categories": self.scope_boundary.get("includes", []),
            "excludes_categories": self.scope_boundary.get("excludes", []),
            "created_at": self.created_at.isoformat(),
            "updated_at": self.updated_at.isoformat()
        }

    def validate_completeness(self) -> Dict[str, Any]:
        """验证范围完整性"""
        issues = []

        # 检查核心功能
        if not self.core_functions:
            issues.append("核心功能列表不能为空")

        # 检查范围边界
        if not self.scope_boundary.get("includes"):
            issues.append("必须包含至少一个功能类别")

        # 检查理由
        if len(self.justification.strip()) < 10:
            issues.append("范围定义理由过于简单")

        # 检查功能重叠
        overlap = set(self.core_functions) & set(self.excluded_functions)
        if overlap:
            issues.append(f"功能重叠: {', '.join(overlap)}")

        return {
            "is_valid": len(issues) == 0,
            "issues": issues,
            "score": max(0, 100 - len(issues) * 20)  # 简单评分机制
        }

    def to_dict(self) -> Dict[str, Any]:
        """转换为字典"""
        return {
            "scope_id": self.scope_id,
            "scope_name": self.scope_name,
            "core_functions": self.core_functions,
            "excluded_functions": self.excluded_functions,
            "scope_boundary": self.scope_boundary,
            "justification": self.justification,
            "created_at": self.created_at.isoformat(),
            "updated_at": self.updated_at.isoformat()
        }

    @classmethod
    def from_dict(cls, data: Dict[str, Any]) -> 'RequirementScope':
        """从字典创建实例"""
        # 处理日期时间
        created_at = datetime.fromisoformat(data["created_at"]) if data.get("created_at") else datetime.now()
        updated_at = datetime.fromisoformat(data["updated_at"]) if data.get("updated_at") else datetime.now()

        return cls(
            scope_id=data["scope_id"],
            scope_name=data["scope_name"],
            core_functions=data["core_functions"],
            excluded_functions=data.get("excluded_functions", []),
            scope_boundary=data["scope_boundary"],
            justification=data["justification"],
            created_at=created_at,
            updated_at=updated_at
        )

    def to_json(self) -> str:
        """转换为JSON字符串"""
        return json.dumps(self.to_dict(), ensure_ascii=False, indent=2)

    @classmethod
    def from_json(cls, json_str: str) -> 'RequirementScope':
        """从JSON字符串创建实例"""
        data = json.loads(json_str)
        return cls.from_dict(data)

    def __str__(self) -> str:
        """字符串表示"""
        return f"RequirementScope(id={self.scope_id}, name={self.scope_name}, core_functions={len(self.core_functions)})"

    def __repr__(self) -> str:
        """详细字符串表示"""
        return (f"RequirementScope(scope_id='{self.scope_id}', scope_name='{self.scope_name}', "
                f"core_functions={self.core_functions}, excluded_functions={self.excluded_functions})")